// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "../zen.h"

namespace zen {

class ProjectStoreCommand : public ZenCmdBase
{
	virtual ZenCmdCategory& CommandCategory() const override { return g_ProjectStoreCategory; }
};

class DropProjectCommand : public ProjectStoreCommand
{
public:
	DropProjectCommand();
	~DropProjectCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-drop", "Drop project or project oplog"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
};

class ProjectInfoCommand : public ProjectStoreCommand
{
public:
	ProjectInfoCommand();
	~ProjectInfoCommand();
	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-info", "Info on project or project oplog"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
};

class CreateProjectCommand : public ProjectStoreCommand
{
public:
	CreateProjectCommand();
	~CreateProjectCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-create", "Create project, the project must not already exist."};
	std::string		 m_HostName;
	std::string		 m_ProjectId;
	std::string		 m_RootDir;
	std::string		 m_EngineRootDir;
	std::string		 m_ProjectRootDir;
	std::string		 m_ProjectFile;
	bool			 m_ForceUpdate = false;
};

class DeleteProjectCommand : public ProjectStoreCommand
{
public:
	DeleteProjectCommand();
	~DeleteProjectCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-delete", "Delete project and all its oplogs"};
	std::string		 m_HostName;
	std::string		 m_ProjectId;
};

class CreateOplogCommand : public ProjectStoreCommand
{
public:
	CreateOplogCommand();
	~CreateOplogCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-create", "Create oplog in an existing project, the oplog must not already exist."};
	std::string		 m_HostName;
	std::string		 m_ProjectId;
	std::string		 m_OplogId;
	std::string		 m_GcPath;
	bool			 m_ForceUpdate = false;
};

class DeleteOplogCommand : public ProjectStoreCommand
{
public:
	DeleteOplogCommand();
	~DeleteOplogCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-delete", "Delete oplog and all its data"};
	std::string		 m_HostName;
	std::string		 m_ProjectId;
	std::string		 m_OplogId;
};

class ExportOplogCommand : public ProjectStoreCommand
{
public:
	ExportOplogCommand();
	~ExportOplogCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-export",
							   "Export project store oplog to cloud (--cloud), file system (--file) or other Zen instance (--zen)"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
	uint64_t		 m_MaxBlockSize		 = 0;
	uint64_t		 m_MaxChunkEmbedSize = 0;
	bool			 m_EmbedLooseFiles	 = false;
	bool			 m_Force			 = false;
	bool			 m_DisableBlocks	 = false;
	bool			 m_Async			 = false;

	std::string m_CloudUrl;
	std::string m_CloudNamespace;
	std::string m_CloudBucket;
	std::string m_CloudKey;
	std::string m_BaseCloudKey;
	std::string m_CloudOpenIdProvider;
	std::string m_CloudAccessToken;
	std::string m_CloudAccessTokenEnv;
	std::string m_CloudAccessTokenPath;
	bool		m_CloudAssumeHttp2		   = false;
	bool		m_CloudDisableTempBlocks   = false;
	bool		m_IgnoreMissingAttachments = false;

	std::string m_ZenUrl;
	std::string m_ZenProjectName;
	std::string m_ZenOplogName;
	bool		m_ZenClean;

	std::string m_FileDirectoryPath;
	std::string m_FileName;
	std::string m_BaseFileName;
	bool		m_FileForceEnableTempBlocks = false;
};

class ImportOplogCommand : public ProjectStoreCommand
{
public:
	ImportOplogCommand();
	~ImportOplogCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-import",
							   "Import project store oplog from cloud (--cloud), file system (--file) or other Zen instance (--zen)"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
	std::string		 m_GcPath;
	size_t			 m_MaxBlockSize				= 0;
	size_t			 m_MaxChunkEmbedSize		= 0;
	bool			 m_Force					= false;
	bool			 m_Async					= false;
	bool			 m_IgnoreMissingAttachments = false;
	bool			 m_Clean					= false;

	std::string m_CloudUrl;
	std::string m_CloudNamespace;
	std::string m_CloudBucket;
	std::string m_CloudKey;
	std::string m_CloudOpenIdProvider;
	std::string m_CloudAccessToken;
	std::string m_CloudAccessTokenEnv;
	std::string m_CloudAccessTokenPath;
	bool		m_CloudAssumeHttp2 = false;

	std::string m_ZenUrl;
	std::string m_ZenProjectName;
	std::string m_ZenOplogName;

	std::string m_FileDirectoryPath;
	std::string m_FileName;
};

class SnapshotOplogCommand : public ProjectStoreCommand
{
public:
	SnapshotOplogCommand();
	~SnapshotOplogCommand();

	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-snapshot", "Snapshot external file references in project store oplog into zen"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
};

class ProjectStatsCommand : public ProjectStoreCommand
{
public:
	ProjectStatsCommand();
	~ProjectStatsCommand();
	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-stats", "Stats info on project store"};
	std::string		 m_HostName;
};

class ProjectDetailsCommand : public ProjectStoreCommand
{
public:
	ProjectDetailsCommand();
	~ProjectDetailsCommand();
	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"project-details", "Detail info on project store"};
	std::string		 m_HostName;
	bool			 m_Details;
	bool			 m_OpDetails;
	bool			 m_AttachmentDetails;
	bool			 m_CSV;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
	std::string		 m_OpId;
};

class OplogMirrorCommand : public ProjectStoreCommand
{
public:
	OplogMirrorCommand();
	~OplogMirrorCommand();
	virtual int				  Run(const ZenCliOptions& GlobalOptions, int argc, char** argv) override;
	virtual cxxopts::Options& Options() override { return m_Options; }

private:
	cxxopts::Options m_Options{"oplog-mirror", "Mirror oplog to file system"};
	std::string		 m_HostName;
	std::string		 m_ProjectName;
	std::string		 m_OplogName;
	std::string		 m_MirrorRootPath;
};

}  // namespace zen
